package bjut.core.postprocessor;

import bjut.core.annotation.Autowired;
import bjut.core.annotation.Qualifier;
import bjut.core.annotation.Value;
import bjut.core.aware.BeanFactoryAware;
import bjut.core.exception.BeansException;
import bjut.core.factory.BeanFactory;
import bjut.core.factory.ConfigurableListableBeanFactory;
import bjut.core.property.PropertyValues;
import bjut.core.util.ClassUtil;
import cn.hutool.core.bean.BeanUtil;

import java.lang.reflect.Field;

/**
 * @Author: zhuzhiming
 * @Date: 2022/6/11 19:10
 */
public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {

    private ConfigurableListableBeanFactory beanFactory;


    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {

        //处理 @value
        Class<?> beanClass = bean.getClass();
        beanClass = ClassUtil.isCglibProxyClass(beanClass) ? beanClass.getSuperclass() : beanClass;

        Field[] declaredFields = beanClass.getDeclaredFields();
        for (Field field : declaredFields) {

            Value valueAnnotation = field.getAnnotation(Value.class);
            if (null != valueAnnotation) {
                String value = valueAnnotation.value();
                value = beanFactory.resolveEmbeddedValue(value);
                BeanUtil.setFieldValue(bean, field.getName(), value);
            }
        }
        // 处理注解@Autowired
        for (Field field : declaredFields) {

            Autowired autowiredAnnotation = field.getAnnotation(Autowired.class);
            if (null != autowiredAnnotation) {
                Class<?> fieldType = field.getType();
                String dependentBeanName = null;
                Qualifier qualifierAnnotation = field.getAnnotation(Qualifier.class);
                Object dependentBean = null;
                if (null != qualifierAnnotation) {
                    dependentBeanName = qualifierAnnotation.value();
                    dependentBean = beanFactory.getBean(dependentBeanName, fieldType);
                } else {
                    dependentBean = beanFactory.getBean(fieldType);
                }
                BeanUtil.setFieldValue(bean, field.getName(), dependentBean);
            }
        }
        return pvs;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }

    @Override
    public Object postBeanPostProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postBeanPostProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return beanClass;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }


}
